package core;

import java.io.*;
import java.net.*;

/* 
 * os helpers trocam mensagens do tipo:
 * (int,int,int,int) -> quem mandou, para quem, numero garfo, QueroObter/EstouLiberando/Ocupado)
 *  
 */

/**
 * essa classe faz a comunição com o sistema distribuido!
 * @author jjeske
 *
 */
public class Helper implements Runnable {	
	
	private boolean[] garfoEsq = new boolean[5]; //false é livre, true é ocupado
	private boolean[] garfoDir = new boolean[5];
	
	//private int[] garfosAlheios = new int[5];
	
	private static int ESTOU_LIBERANDO = 0;
	private static int QUERO_OBTER = 1;
	private static int ESTA_OCUPADO = 2; //isso é só um feedback
	private static int ESTA_LIVRE = 3; //isso é só um feedback
	
	/**
	 * envia um mensagem POP para todos e espera o retorn de todos,
	 * libera o garfo se todos concordarem
	 * POP = acquire
	 * @param numeroGarfo
	 */
	public boolean pop(int numeroGarfo){	
		
		return false;		
	}
	
	/**
	 * envia uma mensagem de VOP para todos e aguarda um retorno confirmado
	 * VOP = liberar o garfo
	 * @param numeroGarfo
	 */
	public void vop(int numeroGarfo, int idFilosofo){
		
		for(int i=0;i<5;i++){ //broadcast
			if(i != idFilosofo){
				Socket clientSocket;
				try {
					clientSocket = new Socket("localhost",6789);
					//DataInputStream in = new DataInputStream(clientSocket.getInputStream());
					DataOutputStream out = new DataOutputStream(clientSocket.getOutputStream());
					out.writeInt(idFilosofo);
					out.writeInt(i); //fazer broadcast !
					out.writeInt(numeroGarfo);
					out.writeInt(ESTA_LIVRE);
					out.close();
					clientSocket.close();	
				} catch (UnknownHostException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}			
			}
		}
		
		//return true;
	}	

	/**
	 * essa parte fica em idle escutando e enviando mensagens o tempo todo
	 */
	@Override
	public void run() {
		ServerSocket serverSocket = null;
		Socket clientSocket = null; //TODO: 5 garfos !
		try {
			serverSocket = new ServerSocket(6789);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		while(true){
			//fica esperando mensagens que recebe e respondendo pra elas!
			try {
				clientSocket = serverSocket.accept();
				//Cria um canal para receber dados.
				DataInputStream in = new DataInputStream(clientSocket.getInputStream());
				//Cria um canal para enviar dados.
				DataOutputStream out = new DataOutputStream(clientSocket.getOutputStream());
				
				int quemMandou = in.readInt();
				int paraQuem = in.readInt();
				int qualGarfo = in.readInt();
				int operacao = in.readInt();			
				System.out.println("quem mandou: " + quemMandou + " paraQuem: " + paraQuem + " garfo: " + " operacao: " + operacao);
				trataOperacao(operacao, qualGarfo);
				in.close();
				out.close();
				clientSocket.close();				
			} catch (IOException e) {
				System.out.println("nao aceitou conexao");
				e.printStackTrace();
			}			
		}
		
	}

	public Helper(int numeroGarfoEsq, int numeroGarfoDir) {
		//super();
		for(int i=0; i<5; i++){ //precisa perguntar pros outros se else estão usando???
			this.garfoDir[i] = false;
			this.garfoEsq[i] = false;
		}		
	}
	
	private static void trataOperacao(int operacao, int qualGarfo){
		if(operacao == ESTOU_LIBERANDO){
			//checa se o numero do garfo é esperado,
				//se for, coloca na fila de espera pelas confirmacoes dos outros
				//se nao for, manda retorn da mensagem liberando garfo
		}
		
		if(operacao == QUERO_OBTER){
			//checa se o numero do garfo é pertencente
				//se for checa se está ocupado ou não
					//se estiver ocupado, manda um retorno dizendo que esta ocupado
					//se estiver livre, manda livre
			    //se o garfo nao pertence, manda livre
		}
		
		if(operacao == ESTA_OCUPADO){
			//checa se o garfo é pertencente
				//TODO: checa se esta esperando por esse garfo
					// se estiver esperando escreve na fila de espera que está ocupado, manda mensagem querendo obter o garfo
					// se nao estiver esperando, manda livre
			//se garfo nao pertence retorna com livre			
		}
		
		if(operacao == ESTA_LIVRE){
			//checa se garfo é pertencente
				//checa se esta esperando por esse garfo
					//se estiver esperando, coloca na fila que está livre, manda mensagem de esta_ocupado
					//se nao estiver esperando nao faz nada. -- overhead de mesnagens			
			//se garfo nao pertence  NAO FAZ NADA! - se nao da overhead de mensagens!
		}
		
	}
}



